﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Threading;
using Serietheque.Properties;

namespace Serietheque.Fenetres
{
    /// <summary>
    /// Logique d'interaction pour Progression.xaml
    /// </summary>
    public partial class Progression : Window
    {
        #region Membres
        private BackgroundWorker bwAjoutBiblio;
        private BackgroundWorker bwRanger;
        private ObservableCollection<Episode> m_episodeCollection;
        private List<string> filenames;
        private List<Episode> m_episodes;
        private bool p;
        #endregion

        #region Constructeurs
        /// <summary>
        /// Constructeur par défaut
        /// </summary>
        public Progression()
        {
            InitializeComponent();
            StopBtn.IsEnabled = true;
        }

        /// <summary>
        /// Création de la bibliotheque
        /// </summary>
        /// <param name="p">true pour création, false pour maj</param>
        public Progression(List<string> fichier, ObservableCollection<Episode> episodeCollection, bool p)
            : this()
        {
            //creationBiblio = p;
            //Membre
            filenames = fichier;
            //Maj du nombre de fichier dans l'ui
            totalTB.Text = filenames.Count.ToString();
            //Définition de la collection d'épisode
            m_episodeCollection = episodeCollection;
            //Création bgw
            bwAjoutBiblio = new BackgroundWorker();
            //Initialisation bgw
            InitializeBackgroundWorker(bwAjoutBiblio);
            //Lancement du bgw
            bwAjoutBiblio.RunWorkerAsync(filenames);
        }

        public Progression(List<Episode> episodes)
            : this()
        {
            m_episodes = episodes;
            totalTB.Text = episodes.Count.ToString();
            bwRanger = new BackgroundWorker();
            InitializeBackgroundWorker(bwRanger);
            bwRanger.RunWorkerAsync(episodes);
        }

        public Progression(ObservableCollection<Episode> m_episodeCollection, bool p)
            : this()
        {
            InitializeComponent();
            StopBtn.IsEnabled = true;
            this.m_episodeCollection = m_episodeCollection;
            this.p = p;
        }
        #endregion

        #region BackgroundWorker Initialisation et fonction

        private void InitializeBackgroundWorker(BackgroundWorker bw)
        {
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
            bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
            bw.WorkerReportsProgress = true;
            bw.WorkerSupportsCancellation = true;
        }

        private void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            if (sender == bwAjoutBiblio)
                AjoutBiblio((List<string>)e.Argument, worker, e);
            if (sender == bwRanger)
                Deplacer((List<Episode>)e.Argument, worker, e);
        }

        private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            pbProcessing.Value = e.ProgressPercentage;

            object[] ob = (object[])e.UserState;
            Episode episode = (Episode)ob.GetValue(1);
            string[] texte = (string[])ob.GetValue(0);

            if (String.Compare(Path.GetExtension(episode.CheminFichier), ".avi", true) == 0 && !m_episodeCollection.Contains(episode))
                m_episodeCollection.Add(episode); //Ajout a la collection de l'episode OK

            //TaskbarManager.Instance.SetProgressValue(50, 100);
            if (texte.Length > 2)
                resultat.Inlines.Add(texte.GetValue(0) + " --> " + texte.GetValue(1) + Environment.NewLine + texte.GetValue(2) + Environment.NewLine + " --> " + texte.GetValue(3) + Environment.NewLine + Environment.NewLine);
            else
                resultat.Inlines.Add(texte.GetValue(0) + Environment.NewLine);
        }

        private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled == true)
                MessageBox.Show("Annulé");

            StopBtn.IsEnabled = false;
            ok.IsEnabled = true;
        }
        #endregion

        #region Méthode effectuer asynchrone
        private void Deplacer(List<Episode> episodes, BackgroundWorker worker, DoWorkEventArgs e)
        {
            int n = 0;
            foreach (Episode episode in episodes)
            {
                this.Dispatcher.Invoke(DispatcherPriority.Background, (ThreadStart)delegate
                {
                    enCourTB.Text = episode.CheminFichier;
                    numTB.Text = (n + 1).ToString();
                });

                //if (!String.IsNullOrEmpty(episode.NomSerie) && Regex.IsMatch(episode.NomSerie, @"([#/\$!*:<>\?])"))
                //string nomSerie = NvNom(episode.NomSerie);

                string nomSerie = Regex.Replace(episode.NomSerie, @"([#/\$!*:<>\?])", "");
                string numEpisode;

                if (Int32.Parse(episode.NumEpisode) < 10)
                    numEpisode = "0" + episode.NumEpisode;
                else
                    numEpisode = episode.NumEpisode;

                string cheminDossier = Settings.Default.Serie + "\\" + nomSerie + "\\Saison " + episode.NumSaison + "\\";

                if (!Directory.Exists(cheminDossier))
                    Directory.CreateDirectory(cheminDossier);

                if (File.Exists(episode.CheminFichier))
                {
                    string nouveauNom = nomSerie + " - " + episode.NumSaison + "x" + numEpisode;

                    if (!String.IsNullOrWhiteSpace(episode.NomEpisode))
                    {
                        string nomEpisode = episode.NomEpisode;
                        if (Regex.IsMatch(nomEpisode, @"([#/\$!*:<>\?])"))
                            nouveauNom = NvNom(nomEpisode);
                        nouveauNom += " - " + nomEpisode;
                    }

                    string extension = Path.GetExtension(episode.CheminFichier);

                    string nouveauChemin = cheminDossier + nouveauNom + extension;
                    if (!File.Exists(nouveauChemin))
                        try
                        {
                            File.Move(episode.CheminFichier, nouveauChemin);
                            episode.CheminFichier = nouveauChemin;
                        }
                        catch { }
                }
            }

            n++;
            int percentProgress = (int)((float)n / (float)episodes.Count * 100);
            bwRanger.ReportProgress(percentProgress);
        }

        private void AjoutBiblio(List<string> filenames, BackgroundWorker worker, DoWorkEventArgs e)
        {
            int n = 0;

            foreach (string cheminFichier in filenames)
            {
                if (worker.CancellationPending)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    this.Dispatcher.Invoke(DispatcherPriority.Background, (ThreadStart)delegate
                        {
                            enCourTB.Text = cheminFichier;
                            numTB.Text = (n + 1).ToString();
                        });

                    string extension = Path.GetExtension(cheminFichier);
                    string[] texte = new string[4];
                    Episode episode = new Episode(cheminFichier, Dispatcher);
                    //Si l'episode n'est pas ok on ouvre la fenetre de dialogue permettant de le modifier
                    if (!episode.Ok)
                    {
                        this.Dispatcher.Invoke(DispatcherPriority.Background, (ThreadStart)delegate //Pour ouvrir sur un autre thread
                           {
                               ModifierEpisode mew = new ModifierEpisode(episode);

                               mew.ShowDialog();

                               episode = mew.EpisodeMod;
                           });
                    }

                    if (episode.Ok && File.Exists(episode.CheminFichier))//Si l'episode est OK on le renomme et on le deplace ou pas et on l'enregistre
                    {

                        //if (!String.IsNullOrEmpty(episode.NomSerie) && Regex.IsMatch(episode.NomSerie, @"([#/\$!*:<>\?])"))
                        //Sepisode.NomSerie = NvNom(episode.NomSerie);
                        episode.NomSerie = Regex.Replace(episode.NomSerie, @"([#/\$!*:<>\?])", "");

                        if (Int32.Parse(episode.NumEpisode) < 10)
                            episode.NumEpisode = "0" + episode.NumEpisode;

                        string cheminDossier = String.Concat(Settings.Default.Serie, "\\", episode.NomSerie, "\\Saison ", episode.NumSaison, "\\");

                        string nouveauNom = String.Concat(episode.NomSerie, " - ", episode.NumSaison, "x", episode.NumEpisode);
                        
                        if (!String.IsNullOrWhiteSpace(episode.NomEpisode))
                        {
                            //this.Dispatcher.Invoke(DispatcherPriority.Background, (ThreadStart)delegate
                            // { episode.NomEpisode = NvNom(episode.NomEpisode); });
                            nouveauNom = String.Concat(nouveauNom, " - ", Regex.Replace(episode.NomEpisode, @"([#/\$!*:<>\?])", ""));
                        }

                        if (Settings.Default.MaitienDossier) //si on veux organisé en dossier
                        {

                            string nouveauChemin = String.Concat(cheminDossier, nouveauNom, Path.GetExtension(cheminFichier));
                            if (!File.Exists(nouveauChemin))
                                try
                                {
                                    if (!Directory.Exists(cheminDossier))
                                        Directory.CreateDirectory(cheminDossier);

                                    File.Move(episode.CheminFichier, nouveauChemin);
                                    //On ajoute le fichier a la liste des fichiers traités
                                    texte = new string[4] { episode.NomFichier, nouveauNom, episode.CheminFichier, nouveauChemin };
                                    episode.CheminFichier = nouveauChemin;
                                    episode.NomFichier = nouveauNom;
                                }
                                catch
                                {

                                }
                            else
                                texte = new string[4] { episode.NomFichier, nouveauNom, "Non Déplacé", "Non Déplacé" };
                        }
                        else
                        {
                            string nouveauChemin = Directory.GetParent(episode.CheminFichier).FullName + "\\" + nouveauNom + Path.GetExtension(episode.CheminFichier);
                            File.Move(episode.CheminFichier, nouveauChemin);
                            //On ajoute le fichier a la liste des fichiers traités
                            texte = new string[4] { episode.NomFichier, nouveauNom, episode.CheminFichier, nouveauChemin };
                            episode.CheminFichier = nouveauChemin;
                            episode.NomFichier = nouveauNom;
                        }
                    }

                    n++;//incrémentation du nombre de fichier traité
                    int percentProgress = (int)(n / filenames.Count * 100);//Pourcentage 
                    worker.ReportProgress(percentProgress, new object[] { texte, episode });//Maj de la progressbar
                }
            }
        }
        #endregion

        private void StopBtn_Click(object sender, RoutedEventArgs e)
        {
            //if (bwAjoutBiblio != null)
            this.bwAjoutBiblio.CancelAsync();

            // Disable the Cancel button.
            StopBtn.IsEnabled = false;
        }

        public static string NvNom(string ancienNom)
        {
            Renommer wdw = new Renommer(ancienNom);
            wdw.ShowDialog();
            return wdw.TextFinal;
        }
    }
}

#region WriteToNotepad

//[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
//private static extern bool SendMessage(
//    IntPtr hWnd, uint msg, UIntPtr wParam, IntPtr lParam);

//[DllImport("User32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
//private static extern IntPtr FindWindowEx(
//    IntPtr hWndParent, IntPtr hWndChild, string className, string WindowName);

//private void WriteToNotepad(string text)
//{
//    if (String.IsNullOrEmpty(text))
//        throw new ArgumentException();

//    Process p = Process.Start("notepad.exe");
//    p.WaitForInputIdle(1000);
//    IntPtr hWnd = p.MainWindowHandle;
//    p.Close();
//    p = null;

//    hWnd = FindWindowEx(hWnd, IntPtr.Zero, "Edit", null);
//    if (hWnd == IntPtr.Zero)
//        throw new Win32Exception(Marshal.GetLastWin32Error());

//    text += '\0';
//    GCHandle gch = GCHandle.Alloc(text, GCHandleType.Pinned);
//    SendMessage(hWnd, 0x000C /*WM_SETTEXT*/, UIntPtr.Zero, gch.AddrOfPinnedObject());
//    int pos = text.Length - 1;
//    SendMessage(hWnd, 0x00B1 /*EM_SETSEL*/, (UIntPtr)pos, (IntPtr)pos);
//    SendMessage(hWnd, 0x0102 /*WM_CHAR*/, (UIntPtr)'\n', IntPtr.Zero);
//    gch.Free();
//}
#endregion